package javapop.framework.parser;

import java.util.Arrays;
import java.util.List;

import javapop.framework.ParseContext;
import javapop.framework.ParseError;
import javapop.framework.ParseInput;
import javapop.framework.ParseResult;
import javapop.framework.Parser;

public class Literals extends Parser<String> {
	private List<String> literals;
	private String description;
	private String errMessage;
	
	public Literals(String...literals) {
		if(literals.length<=1)
			throw new IllegalArgumentException("At least two literals expected");
		this.literals = Arrays.asList(literals);
		StringBuffer buf = new StringBuffer();
		buf.append("{ ");
		for(int i=0;i<this.literals.size();i++) {
			buf.append("'");
			buf.append(this.literals.get(i));
			buf.append("'");
			if(i<this.literals.size()) {
				buf.append(", ");
			}
		}
		buf.append(" }");
		description = buf.toString();
		buf = new StringBuffer();
		buf.append("Expecting a literal in ");
		buf.append(description);
		errMessage = buf.toString();
	}
	
	@Override
	public String getDescription() {
		return description;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public ParseResult<String> eval(ParseContext ctx, ParseInput input) {
		for(String literal : literals) {
			if(input.consume(literal)) {
				ParseResult<String> result = buildResult(literal);
				return result;
			}
		}
		
		ParseResult error = new ParseError(errMessage);
		return (ParseResult<String>) error;
	}
	
	@Override
	public boolean isMemoized() {
		return true;
	}
	
	@Override
	public int hashCode() {
		return description.hashCode();
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj==null) return false;
		if(obj==this) return true;
		if(obj.getClass()!=this.getClass())
			return false;
		return ((Literals) obj).literals.equals(literals);
	}

}
